#!/usr/bin/python

import os
import sys
import urllib

from optparse import OptionParser
from lxml.html import parse

# Exit status
status = 0

def check(code, filename, options):
    global status
    try:
        values = {'output': 'html', 'text': code}
        params = ('warning', 'lang', 'profile')
        for param in params:
            if getattr(options, param):
                values.update({param: getattr(options, param)})
        encoded_values = urllib.urlencode(values)
        validator_url = "http://jigsaw.w3.org/css-validator/validator?"
        url = "%s%s" % (validator_url, encoded_values)
        page = parse(url).getroot()
        try:
            congrats = page.get_element_by_id("congrats")
            messages = congrats.cssselect("h3")
            for msg in messages:
                print msg.text_content().strip()
                break
            status = 0
            return 0
        except KeyError:
            for item in ('error', 'warning'):
                messages = page.find_class(item)
                for message in messages:
                    tds = message.cssselect("td")
                    td_list = []
                    for td in tds:
                        import re
                        td_list.append(re.sub(r"[ ]{2,}", ' ', re.sub(r'[\n|\r|\t]+', '', td.text_content())).strip())
                    print u"%s:%s [%s] %s ~ %s" % (filename,
                                             td_list[0],
                                             item,
                                             td_list[1],
                                             " ".join(td_list[2:]).strip())
            status = 1
            return len(messages)
    except Exception, msg:
        print >> sys.stderr, '%r: %s' % (filename, msg)
        status = 2
        return 1

def checkPath(filename, options):
    if os.path.exists(filename):
        fd = file(filename, 'U')
        try:
            return check(fd.read(), filename, options)
        finally:
            fd.close()

def main(args, options):
    warnings = 0
    if args:    
        for arg in args:
            if os.path.isdir(arg):
                for dirpath, dirnames, filenames in os.walk(arg):
                    for filename in filenames:
                        if filename.endswith('.css'):
                            warnings += checkPath(os.path.join(dirpath, filename), options)
            else:
                warnings += checkPath(arg, options)
    else:
        warnings += check(sys.stdin.read(), '<stdin>', options)

    raise SystemExit(warnings > 0)

def process_options(arglist=None):
    """
    Process options passed either via arglist or via command line args.
    """
    global options, args
    usage = "%prog [options] file"
    parser = OptionParser(usage)
    parser.add_option('-w', '--warning', metavar='patterns', default="0",
                      help="warning level (default 0 - no warnings)")
    parser.add_option('-l', '--lang', metavar='patterns', default="en",
                      help="notification language (default en - English)")
    parser.add_option('-p', '--profile', metavar='patterns', default="css2",
                      help="CSS profile for validation: css1, css2, css21, css3, svg, svgbasic, svgtiny, mobile, atsc-tv, tv or none (default css2 - W3C Recomendation)")
    options, args = parser.parse_args(arglist)
    if len(args) == 0:
        parser.error('input not specified')
    options.prog = os.path.basename(sys.argv[0])
    return options, args

if __name__ == '__main__':
    options, args = process_options()
    main(args, options)
    sys.exit(status)
